import java.util.ArrayList;
import java.util.Arrays;

import neural.sbpn;


/**
 * @author Steve Duncan
 * Creates new data and puts the data in the correct position 
 * of the arraylist.
 */
public class CreateMutant {
	static ArrayList<Mutant> data = new ArrayList<Mutant>();
	static ArrayList<Mutant> newData = new ArrayList<Mutant>();
	static int muta[][]= new int[64][6];
	
	// counters and max for each number
	final static int ZEROSIX = 1, ONEFIVE = 6, TWOFOUR = 15, THREE = 20, MUTSIZE = 6;

	public static void setData(ArrayList<Mutant> data) {
		CreateMutant.data = data;
	}

	public static ArrayList<Mutant> getNewData() {
		if(newData.isEmpty()){
			makeZeroArray();
			addOldArray();
			makeNewSite();
			findMax();
		}
		return newData;
	}

	private static void findMax(){
		for(int i = 0; i < newData.size(); i++){			
			double data[] = newData.get(i).getData();
			int maxLoc = newData.get(i).getMaxLocation();
			double maxValue = -1;
			
			for(int j = 0; j < data.length; j++){
				if(data[j] > maxValue){
					maxValue = data[j];
					maxLoc = j;
				}
			}
			newData.get(i).setMaxLocation(maxLoc);
		}
	}
	
	private static void makeNewSite() {
		// loc stores position in NewData that needs a site.
		int[] loc = new int[64];
		int locMax = 0;
		int[] mutation = new int[6];
		// site number -> location in ArrayList
		// all 6 -> 64, 1 -> 2, 2 -> 3, 3 -> 4, 4 -> 5, 5 -> 6, 6 -> 7		
		
		Mutant six = new Mutant();
		Mutant a = new Mutant();
		Mutant b = new Mutant();
		Mutant c = new Mutant();
		Mutant d = new Mutant();
		Mutant e = new Mutant();
		Mutant f = new Mutant();

		six.setName(newData.get(64).getName());
		six.setData(newData.get(64).getData());
		a.setName(newData.get(2).getName());
		a.setData(newData.get(2).getData());
		b.setName(newData.get(3).getName());
		b.setData(newData.get(3).getData());
		c.setName(newData.get(4).getName());
		c.setData(newData.get(4).getData());
		d.setName(newData.get(5).getName());
		d.setData(newData.get(5).getData());
		e.setName(newData.get(6).getName());
		e.setData(newData.get(6).getData());
		f.setName(newData.get(7).getName());
		f.setData(newData.get(7).getData());		

		for(int i = 0; i < newData.size(); i++)
			if(newData.get(i).getName() == "")
				loc[locMax++] = i;

		for(int place = 0; place < locMax; place++){
			Mutant newM = new Mutant();
			mutation = muta[loc[place] - 1];

			//--------------------------
			// attempt at neural network prediction code
			
			sbpn network;
			
			
			
			
			
			
			//--------------------------
			
			
			//------------------------------------------------------------------------
			// original lame prediction code 
			// predict each of the 60 data numbers
			// x = six - ((six - a) + (six - b) ... ) / 2
			
			for(int i = 0; i < six.getData().length; i++){
				double total = 0;
				if(mutation[0] == 1)
					total += six.getData(i) - a.getData(i);
				if(mutation[1] == 1)
					total += six.getData(i) - b.getData(i);
				if(mutation[2] == 1)
					total += six.getData(i) - c.getData(i);
				if(mutation[3] == 1)
					total += six.getData(i) - d.getData(i);
				if(mutation[4] == 1)
					total += six.getData(i) - e.getData(i);
				if(mutation[5] == 1)
					total += six.getData(i) - f.getData(i);							
				
				
				newM.setData(i, (six.getData(i) - total / getMutationSum(mutation)));
			}			
			//------------------------------------------------------------------------

			// build name based on mutation
			String name = "";
			if(mutation[0] == 1)
				name += a.getName() + ", ";
			if(mutation[1] == 1)
				name += b.getName() + ", ";
			if(mutation[2] == 1)
				name += c.getName() + ", ";
			if(mutation[3] == 1)
				name += d.getName() + ", ";
			if(mutation[4] == 1)
				name += e.getName() + ", ";
			if(mutation[5] == 1)
				name += f.getName();			
			if(name.endsWith(", "))
				name = name.substring(0, name.length() - 2);
			
			// set name and data
			newM.setName(name);
			newM.setPrediction(true);
		
			// add to array
			addToArray(newM, findLoc(newM.getMutations()));
		}
	}

	private static int getMutationSum(int[] mut){
		int sum = 0;
		for(int i = 0; i < mut.length; i++)		
			sum += mut[i];
		return sum;		
	}

	/**
	 * "Mel" will live in the 0 spot.
	 */
	private static void addToArray(Mutant site, int loc) {
		// adds to newData array.  Offset of 1 for Mel
		newData.remove(loc + 1);
		newData.add(loc + 1, site);	
	}

	private static int findLoc(int[] mut){
		int loc = -1;
		for(int i = 0; i < muta.length; i++){
			if(Arrays.equals(mut, muta[i]))
				loc = i;
		}
		// returns loc found in muta array
		return loc;
	}

	private static void addOldArray() {
		// add old array to new array
		while(!data.isEmpty()){
			int [] mut = data.get(0).getMutations();
			addToArray(data.remove(0), findLoc(mut));
		}
	}

	private static void makeZeroArray() {
		initMuta();
		for(int i = 0; i < 65; i++)
			newData.add(new Mutant());			
	}

	// needs to make in order
	private static void initMuta(){
		int front = 0;
		int back = muta.length - 1;
		int entry = 0, times = 5;
		int one = 0, two = 0, three = 0;

		// 0 & 6
		for(int i = 0; i < MUTSIZE; i++)
			muta[back][i] = 1;
		front++;
		back--;

		// 1s & 5s
		for(int i = 0; i < ONEFIVE; i++){
			for(int j = 0; j < MUTSIZE; j++)
				muta[back][j] = 1;
			muta[front++][one] = 1;
			muta[back--][one] = 0;
			one++;
		}

		// 2s & 4s
		one = 0;
		two = one + 1;
		entry = 0;
		times = 5;
		for(int i = 0; i < TWOFOUR; i++){
			for(int j = 0; j < MUTSIZE; j++)
				muta[back][j] = 1;			
			if(entry < times){
				muta[front][one] = 1;
				muta[back][one] = 0;
				muta[front][two] = 1;
				muta[back][two] = 0;
				entry++;
				two++;
			}
			if(entry == times){
				entry = 0;
				times--;
				one++;
				two = one + 1;
			}
			front++;
			back--;
		}		

		// 3s
		one = 0;
		two = one + 1;
		three = two + 1;
		entry = 0;
		times = 4;
		for(int i = 0; i < THREE / 2 ; i++){
			for(int j = 0; j < MUTSIZE; j++)
				muta[back][j] = 1;			
			if(entry < times){
				muta[front][one] = 1;
				muta[back][one] = 0;
				muta[front][two] = 1;
				muta[back][two] = 0;
				muta[front][three] = 1;
				muta[back][three] = 0;
				entry++;
				three++;
				if(three > MUTSIZE){
					two++;
					three = two + 1;
				}
			}
			if(entry == times){
				entry = 0;
				times--;
				two++;
				three = two + 1;
			}
			front++;
			back--;
		}		
	}

	public static void main(String[] args) {
		// arraylist setup
		String inputFile = "resources/Melanopsin_Mutants.csv";
		CSVFile.readCSV(inputFile);
		setData(CSVFile.getData());

		// print new data
		for(int i = 0; i < getNewData().size(); i++)
			System.out.println(i + " " + getNewData().get(i).toString());
	}
}
